package com.ruijie.acl.utils;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.regexp.RE;
import org.apache.regexp.RECompiler;
import org.springframework.util.Assert;

import com.ruijie.acl.AccessGroup;
import com.ruijie.acl.Ace;
import com.ruijie.acl.TimeInfo;
import com.ruijie.emp.device.Device;
import com.ruijie.emp.utils.NetUtils;
import com.ruijie.foundation.adapter.utils.ParserUtil;
import com.ruijie.foundation.utils.StringUtils;
import com.ruijie.acl.type.*;

public class AclUtil {

	public static boolean CONFIG_RELEASE_STATE = true;
	private static int uniqueID = 0;
	private static Pattern NUM_PATTERN = Pattern.compile("[0-9]+");
	/*
	 * 不包含中文和全角字符的正则表达式
	 */
	private static Pattern NOT_CN_FULL_PATTERN = Pattern.compile("[^\u4e00-\u9fa5\uFF00-\uFFFF]+");

	/**
	 * 转义用数组



	 */
	private static String[][] ESCAPEARRAY = { { "&", "&amp#" }, { ",", "&comma#" }, { ";", "&semicolon#" } };
	/**
	 * 允许使用的端口字符串列表
	 */
	private static List<String> portAllowStringList = new ArrayList<String>();

	public static List<String> getPortAllowStringList() {
		if (portAllowStringList == null || portAllowStringList.size() == 0) {
			for (PortTypeEnum protTypeEnum : PortTypeEnum.values()) {
				portAllowStringList.add(protTypeEnum.value());
			}
		}
		return portAllowStringList;
	}

	/**
	 * 是否为NULL或许为空
	 * 
	 * @param str
	 * @return
	 */
	public static boolean empty(String str) {
		return str == null || str.trim().length() == 0;
	}

	/**
	 * 两个字符串是否相等



	 * 
	 * @param str1
	 *            字符串1
	 * @param str2
	 *            字符串2
	 * @return
	 */
	public static boolean equals(String str1, String str2) {
		if (empty(str1)) {
			// 如果两个都为空或许NULL，则返回True
			if (empty(str2)) {
				return true;
			} else {
				return false;
			}
		} else {
			return str1.equals(str2);
		}
	}

	/**
	 * 字符串转换数字



	 * 
	 * @param s
	 *            待转换字符串
	 * @return 转换后的数字
	 */
	private static int parseInt(String s) {
		try {
			return Integer.valueOf(s);
		} catch (NumberFormatException ne) {
			return -1;
		}
	}

	/**
	 * 掩码取反
	 * 
	 * @param mask
	 *            掩码
	 * @return 取反后的掩码
	 */
	public static String reverseMask(String mask) {
		String result = "";
		if (mask == null) {
			return "";
		} else {
			String[] sip = mask.split("\\.");
			if (sip.length != 4) {
				return "";
			}
			if (mask.lastIndexOf('.') == mask.getBytes().length - 1) {
				return "";
			}
			for (String sub : sip) {
				int subInt = parseInt(sub);
				if (subInt == -1) {
					return "";
				} else {
					result += "." + String.valueOf(255 - subInt);
				}
			}
			if (result.length() > 0) {
				result = result.substring(1);
			}
		}
		return result;
	}

	public static String translateNetipByMask(String ip, String mask) {
		if (!NetUtils.ipV4SubNetValidator(ip))
			return null;
		if (!NetUtils.maskValidator(mask))
			return null;
		byte[] netip = NetUtils.ip2bytes(ip);
		byte[] netMask = NetUtils.ip2bytes(mask);
		for (int i = 0; i < netip.length; i++) {
			netip[i] = (byte) (netip[i] & netMask[i]);
		}
		return NetUtils.byteToString(netip);
	}

	public static Date addDay(Date date, int n) {
		try {
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(date);
			calendar.add(Calendar.DATE, n);
			return calendar.getTime();
		} catch (Exception ex) {
			return date;
		}
	}

	/**
	 * 判断设备软件版本是否是旧版



	 * 
	 * @param device
	 *            设备
	 * @return 设备软件版本是否是旧版



	 */
	public static boolean isOldVersion(Device device) {
		// RGNOS 10.1.00(4), Release(18437)
		String ver = "";
		double deviceSoftwareVersion = 0;
		try {
			if (device != null) {
				ver = device.getSoftwareVersion();
				ParserUtil parserUtil = new ParserUtil();
				if (parserUtil.addRegexp(ver, "VER", "RG\\S*OS\\s*(\\d+\\.\\d+)")) {
					ver = parserUtil.get("VER.1");
				}
			}
		} catch (Exception ex) {
			ver = "0";
		}
		try {
			deviceSoftwareVersion = Double.parseDouble(ver);
		} catch (Exception ex) {
			deviceSoftwareVersion = 0;
		}
		return deviceSoftwareVersion < 10.4;
	}
	
	/**
	 * 对时间列表进行过滤
	 * @param timeInfo
	 * @return
	 */
	public static boolean filterTimeInfo(TimeInfo timeInfo){
		String regex="([0-9]|([0-1][0-9])|(2[0-3])):([0-9]|([0-5][0-9]))";
		String newPeriodic = timeInfo.getPeriodic().toLowerCase();
		String[] periodics = newPeriodic.split(" ");
		for(String periodic:periodics){
			try {
				TimeInfoTypeEnum.valueOf(periodic);
				
			} catch (Exception e) {
				return false;
			}
		}
		timeInfo.setPeriodic(newPeriodic);
		if(!timeInfo.getStarttime().matches(regex) || !timeInfo.getEndtime().matches(regex)){
			return false;
		}else{
			String startTimes[] = timeInfo.getStarttime().split(":");
			String endTimes[] = timeInfo.getEndtime().split(":");
			Calendar startCalendar = Calendar.getInstance();
			startCalendar.set(2009, 10, 1, Integer.parseInt(startTimes[0]), Integer.parseInt(startTimes[1]), 0);
			Calendar endCalendar = Calendar.getInstance();
			endCalendar.set(2009, 10, 1, Integer.parseInt(endTimes[0]), Integer.parseInt(endTimes[1]), 0);
			// 开始时间不能大于或者等于结束时间
			if (startCalendar.compareTo(endCalendar) >= 0) {
				return false;
			}
		}
		return true;
	}
	
	
	
	/**
	 * 对规则进行过滤：根据规则类型，对相关栏位进行置空处理
	 * 
	 * @param ace
	 *            ACL规则
	 * @param aceType
	 *            规则类型
	 */
	public static void filterAce(Ace ace, String aceType) { 
		Assert.notNull(aceType);
		if(empty(ace.getTimeRangeName())){
			ace.setTimeRangeName(null);
		}
		/*
		 * ace.setVlanNum(null); // 置空Vlan编号
		 * ace.setProtocolType(null); // 置空协议类型
		 * ace.setSourceMacAddr(null); // 置空源Mac地址
		 * ace.setSourceMacMatchType(null); // 置空源Mac匹配类型
		 * ace.setDesMacAddr(null); // 置空目的Mac地址 ace.setDesMacMatchType(null); //
		 * 置空目的Mac匹配类型 ace.setEthernetType(null); // 置空以太网类型
		 * ace.setDesAddr(null); // 置空目的地址 ace.setDesMatchType(null); //
		 * 置空目的匹配类型 ace.setDesWildcard(null); // 置空目的通配符 ace.setDesPort(null); //
		 * 置空目的端口
		 * ace.setSourceAddr(null); // 置空源地址 ace.setSourceMatchType(null); //
		 * 置空源匹配类型 ace.setSourceWildcard(null); // 置空源通配符
		 * ace.setSourcePort(null); // 置空源端口
		 */
		if (AceTypeEnum.STANDARD.toString().equals(aceType)) {
			// 标准规则
			ace.setVlanNum(null); // 置空Vlan编号
			ace.setProtocolType(null); // 置空协议类型
			ace.setSourceMacAddr(null); // 置空源Mac地址
			ace.setSourceMacMatchType(null); // 置空源Mac匹配类型
			ace.setDesMacAddr(null); // 置空目的Mac地址
			ace.setDesMacMatchType(null); // 置空目的Mac匹配类型
			ace.setEthernetType(null); // 置空以太网类型

			ace.setDesAddr(null); // 置空目的地址
			ace.setDesMatchType(null); // 置空目的匹配类型
			ace.setDesWildcard(null); // 置空目的通配符

			ace.setDesPort(null); // 置空目的端口
			ace.setSourcePort(null); // 置空源端口
		} else if (AceTypeEnum.EXTENDED.toString().equals(aceType)) {
			// 扩展规则
			ace.setVlanNum(null); // 置空Vlan编号

			ace.setSourceMacAddr(null); // 置空源Mac地址
			ace.setSourceMacMatchType(null); // 置空源Mac匹配类型
			ace.setDesMacAddr(null); // 置空目的Mac地址
			ace.setDesMacMatchType(null); // 置空目的Mac匹配类型
			ace.setEthernetType(null); // 置空以太网类型
		} else if (AceTypeEnum.MAC.toString().equals(aceType)) {
			// Mac扩展
			ace.setVlanNum(null); // 置空Vlan编号

			ace.setProtocolType(null); // 置空协议类型

			ace.setDesAddr(null); // 置空目的地址
			ace.setDesMatchType(null); // 置空目的匹配类型
			ace.setDesWildcard(null); // 置空目的通配符
			ace.setDesPort(null); // 置空目的端口

			ace.setSourceAddr(null); // 置空源地址
			ace.setSourceMatchType(null); // 置空源匹配类型
			ace.setSourceWildcard(null); // 置空源通配符
			ace.setSourcePort(null); // 置空源端口

			//MAC地址的转换
			ace.setSourceMacAddr(AclUtil.correctMac(ace.getSourceMacAddr()));
			ace.setDesMacAddr(AclUtil.correctMac(ace.getDesMacAddr()));
			
			//过滤以太网类型

			if(ace.getEthernetType()!=null&&ace.getEthernetType().trim().length()==0){
				ace.setEthernetType(null);
			}

		} else if (AceTypeEnum.EXPERT.toString().equals(aceType)) {
			// 专家扩展
			ace.setEthernetType(null); // 置空以太网类型
			//MAC地址的转换
			ace.setSourceMacAddr(AclUtil.correctMac(ace.getSourceMacAddr()));
			ace.setDesMacAddr(AclUtil.correctMac(ace.getDesMacAddr()));
			//过滤VLan编号
			if(ace.getVlanNum()!=null&&ace.getVlanNum().trim().length()==0){
				ace.setVlanNum(null);
			}
			//过滤协议类型
			if(ace.getProtocolType()!=null&&ace.getProtocolType().trim().length()==0){
				ace.setProtocolType(null);
			}
			//过滤Vlan编号开头多余的零
			ace.setVlanNum(AclUtil.trimZero(ace.getVlanNum()));
		}

		/** ********************二级规则过滤************************** */

		if (AceTypeEnum.STANDARD.toString().equals(aceType)) {
			/*
			 * a) 源匹配类型：所有ip、主机、网段。 b) 源地址：当源匹配类型为"主机"、"网段"时才能录入或显示。IP地址不支持区间输入。
			 * c) 源通配符：当源匹配类型为"网段"时才能录入或显示。
			 */
			String sourceMatchType = ace.getSourceMatchType();
			if (MatchTypeEnum.any.toString().equals(sourceMatchType)) {
				ace.setSourceAddr(null); // 置空源地址
				ace.setSourceWildcard(null); // 置空源通配符
			} else if (MatchTypeEnum.host.toString().equals(sourceMatchType)) {
				ace.setSourceWildcard(null); // 置空源通配符
			}
		}
		if (AceTypeEnum.EXPERT.toString().equals(aceType) || AceTypeEnum.EXTENDED.toString().equals(aceType)) {
			/*
			 * a) 源匹配类型：所有ip、主机、网段。 b) 源地址：当源匹配类型为"主机"、"网段"时才能录入或显示。IP地址不支持区间输入。
			 * c) 源通配符：当源匹配类型为"网段"时才能录入或显示。
			 * 			 */
			String sourceMatchType = ace.getSourceMatchType();
			if (MatchTypeEnum.any.toString().equals(sourceMatchType)) {
				ace.setSourceAddr(null); // 置空源地址
				ace.setSourceWildcard(null); // 置空源通配符
			} else if (MatchTypeEnum.host.toString().equals(sourceMatchType)) {
				ace.setSourceWildcard(null); // 置空源通配符
			}
			/*
			 * a) 目的匹配类型：所有ip、主机、网段。 b)
			 * 目的地址：当目的匹配类型为"主机"、"网段"时才能录入或显示。IP地址不支持区间输入。 c)
			 * 目的通配符：当目的匹配类型为"网段"时才能录入或显示。
			 */
			String desMatchType = ace.getDesMatchType();
			if (MatchTypeEnum.any.toString().equals(desMatchType)) {
				ace.setDesAddr(null); // 置空目的地址
				ace.setDesWildcard(null); // 置空目的通配符
			} else if (MatchTypeEnum.host.toString().equals(desMatchType)) {
				ace.setDesWildcard(null); // 置空目的通配符
			}
			/*
			 * e) 源端口：当协议类型为tcp、udp时才能录入或显示。值为0 ~ 65535。 i)
			 * 目的端口：当协议类型为tcp、udp时才能录入或显示。值为0 ~ 65535。
			 */
			String protocol = ace.getProtocolType();
			if (!(ProtocolTypeEnum.tcp.toString().equals(protocol) || ProtocolTypeEnum.udp.toString().equals(protocol))) {
				ace.setSourcePort(null); // 置空源端口
				ace.setDesPort(null); // 置空目的端口
			}
		}
		if (AceTypeEnum.MAC.toString().equals(aceType) || AceTypeEnum.EXPERT.toString().equals(aceType)) {
			/*
			 * a) 源MAC匹配类型：所有mac、主机。 b) 源MAC地址：当源MAC匹配类型为"主机"时才能录入或显示。
			 */
			String sourceMacMatchType = ace.getSourceMacMatchType();
			if (!MacMatchTypeEnum.host.toString().equals(sourceMacMatchType)) {
				ace.setSourceMacAddr(null); // 置空源Mac地址
			}
			/*
			 * a) 目的MAC匹配类型：所有mac、主机。 b) 目的MAC地址：当目的MAC匹配类型为"主机"时才能录入或显示。
			 */
			String desMacMatchType = ace.getDesMacMatchType();
			if (!MacMatchTypeEnum.host.toString().equals(desMacMatchType)) {
				ace.setDesMacAddr(null); // 置空目的Mac地址
			}
		}
		//[start]处理源目通配符的转换
		if (ace.getSourceWildcard() != null && ace.getSourceAddr() != null
				&& AclUtil.wildcardValidator(ace.getSourceAddr()) && AclUtil.wildcardValidator(ace.getSourceWildcard())) {
			ace.setSourceAddr(convertIpWithWildcard(ace.getSourceAddr(), ace.getSourceWildcard()));
		}
		if (ace.getDesWildcard() != null && ace.getDesAddr() != null && AclUtil.wildcardValidator(ace.getDesAddr())
				&& AclUtil.wildcardValidator(ace.getDesWildcard())) {
			ace.setDesAddr(convertIpWithWildcard(ace.getDesAddr(), ace.getDesWildcard()));
		}
		//[end]
		//[start]过滤源目端口的前后空格,前面多余的零
		if(ace.getSourcePort()!=null){
			String port=ace.getSourcePort().trim();
			if(port.length()==0){
				ace.setSourcePort(null);
			}else{
				ace.setSourcePort(AclUtil.trimZero(port));
			}
		}
		if(ace.getDesPort()!=null){
			String port=ace.getDesPort().trim();
			if(port.length()==0){
				ace.setDesPort(null);
			}else{
				ace.setDesPort(AclUtil.trimZero(port));
			}
		}
		//[end]
		
		//[start]专家扩展时协议类型导致栏位的变化
		if(AceTypeEnum.EXPERT.toString().equals(aceType)){
			String protocolType=ace.getProtocolType();
			boolean isEthernetType=false;
			try{
				EthernetTypeEnum.valueOf(protocolType);
				isEthernetType=true;
			}catch(Exception e){
				isEthernetType=false;
			}
			if(isEthernetType){
				//以太网协议类型，置空与IP有关的栏位
				ace.setDesAddr(null); // 置空目的地址
				ace.setDesMatchType(null); // 置空目的匹配类型
				ace.setDesWildcard(null); // 置空目的通配符
				ace.setDesPort(null); // 置空目的端口

				ace.setSourceAddr(null); // 置空源地址
				ace.setSourceMatchType(null); // 置空源匹配类型
				ace.setSourceWildcard(null); // 置空源通配符
				ace.setSourcePort(null); // 置空源端口
			}
		}			
		//[end]
		//[start]源目端口的转换，根据tcp或udp，将80转换为www等
		if(AceTypeEnum.EXPERT.toString().equals(aceType)
				||AceTypeEnum.EXTENDED.toString().equals(aceType)){
			ace.setSourcePort(PortTypeEnum.getPortString(ace.getSourcePort(), ace.getProtocolType()));
			ace.setDesPort(PortTypeEnum.getPortString(ace.getDesPort(), ace.getProtocolType()));
		}
		//[end]
	}


	/**
	 * 根据规则类型，检查ACL规则的合法性



	 * 
	 * @param ace
	 *            ACL规则
	 * @param aceType
	 *            规则的类型



	 * @return 成功返回""，失败返回失败原因字符串
	 */
	public static String validateAce(Ace ace, String aceType) {
		// [start]动作类型
		String actionType = ace.getActionType().trim();
		if (!ActionTypeEnum.deny.toString().equals(actionType) && !ActionTypeEnum.permit.toString().equals(actionType)) {
			// 未知的动作类型
			return "acl_ace_validate_actionType_unkown";
		}
		// [end]
		
		// [start]MAC以太网协议类型检测,空或为指定类型
		if (AceTypeEnum.MAC.toString().equals(aceType)) {
			String ethernetType = ace.getEthernetType();
			if (!StringUtils.isNullOrEmpty(ethernetType)) {
				try{
					EthernetTypeEnum.valueOf(ethernetType);
				}catch(IllegalArgumentException ie){
					// 未知的以太网协议类型
					return "acl_ace_validate_ethernetType_nokown";
				}
			}
		}
		//[end]
		
		//[start]扩展：协议类型，不能为空
		if(AceTypeEnum.EXTENDED.toString().equals(aceType)){
			String protocolType=ace.getProtocolType();
			if(StringUtils.isNullOrEmpty(protocolType)){
				//扩展：协议类型不能为空
				return "acl_ace_validate_protocoltype_4_extended_no_null";
			}
			try{
				ProtocolTypeEnum.valueOf(protocolType);
			}catch(Exception e){
				//扩展：未知的协议类型
				return "acl_ace_validate_protocoltype_4_extended_unkown";
			}
		}
		//[end]
		
		//[start]专家：协议类型检查，可以为空。协议类型为以太网的类型时，不能包含有IP栏位
		if(AceTypeEnum.EXPERT.toString().equals(aceType)){
			String protocolType=ace.getProtocolType();
			if(!StringUtils.isNullOrEmpty(protocolType)){
				try{
					EthernetProtocolTypeEnum.valueOf(protocolType);
				}catch(Exception e){
					//扩展：未知的协议类型
					return "acl_ace_validate_protocoltype_4_expert_unkown";
				}
				boolean isEthernet=false;
				try{
					EthernetTypeEnum.valueOf(protocolType);
					isEthernet=true;
				}catch(Exception e){
					isEthernet=false;
				}
				if(isEthernet){
					if(!StringUtils.isNullOrEmpty(ace.getSourceAddr())
							||!StringUtils.isNullOrEmpty(ace.getSourceMatchType())
							||!StringUtils.isNullOrEmpty(ace.getSourceWildcard())
							||!StringUtils.isNullOrEmpty(ace.getSourcePort())
							||!StringUtils.isNullOrEmpty(ace.getDesAddr())
							||!StringUtils.isNullOrEmpty(ace.getDesMatchType())
							||!StringUtils.isNullOrEmpty(ace.getDesWildcard())
							||!StringUtils.isNullOrEmpty(ace.getDesPort())){
						//ace_ace_validate_expert_protocol_ethernet=当协议类型为以太网的类型时，规则不能包含IP地址、通配符、IP匹配类型、端口栏位！
						return "ace_ace_validate_expert_protocol_ethernet";
					}
				}
			}
			
		}
		//[end]
		
		// [start]专家扩展：Vlan字段，可以为空，不为空时，Vlan值必须在1~4095
		if (AceTypeEnum.EXPERT.toString().equals(aceType)) {
			String vlanNum = ace.getVlanNum();
			if (!StringUtils.isNullOrEmpty(vlanNum)){
				if(!NUM_PATTERN.matcher(vlanNum).matches()) {
				// vlan字段必须填写数值

				return "acl_ace_validate_vlan_require_num";
				}else{
					//Vlan值必须在1~4095
					int vlan=Integer.parseInt(vlanNum);
					if(vlan<1||vlan>4095){
						return "acl_ace_validate_vlan_scop";
					}
				}
			}			
		}
		// [end]
				
		// [start]标准、专家扩展、扩展ACL：源地址、目的地址。专家扩展的协议类型已经过验证，已保证规则的协议类型不为以太网类型
		if (AceTypeEnum.STANDARD.toString().equals(aceType) 
				|| (AceTypeEnum.EXPERT.toString().equals(aceType))
				|| AceTypeEnum.EXTENDED.toString().equals(aceType)) {
			
			String sourceMatchType = ace.getSourceMatchType();
			String sourceAddr = ace.getSourceAddr();
			String sourceWildCard = ace.getSourceWildcard();
			// 源地址：当源匹配类型为"主机"、"网段"时才能录入或显示。
			if (MatchTypeEnum.any.toString().equals(sourceMatchType)) {
				if (!StringUtils.isNullOrEmpty(sourceAddr) || !StringUtils.isNullOrEmpty(sourceWildCard)) {
					// 当ip地址匹配类型为"所有主机"时，地址和通配符不可录入。
					return "acl_ace_validate_ip_any";
				}
			} else if (MatchTypeEnum.host.toString().equals(sourceMatchType)) {
				if (!StringUtils.isNullOrEmpty(sourceWildCard) || StringUtils.isNullOrEmpty(sourceAddr)
						|| !AclUtil.wildcardValidator(sourceAddr)) {
					// 当ip地址匹配类型为"主机"时，必须输入正确的ip地址，通配符不可录入
					return "acl_ace_validate_ip_host";
				}
			} else if (MatchTypeEnum.segment.toString().equals(sourceMatchType)) {
				if (StringUtils.isNullOrEmpty(sourceWildCard) || StringUtils.isNullOrEmpty(sourceAddr)
						|| !AclUtil.wildcardValidator(sourceAddr) || !AclUtil.wildcardValidator(sourceWildCard)) {
					// 当ip地址匹配类型为"网段"时，必须输入正确的ip地址和通配符
					return "acl_ace_validate_ip_segment";
				}
			}		

			String desMatchType = ace.getDesMatchType();
			String desAddr = ace.getDesAddr();
			String desWildCard = ace.getDesWildcard();
			// 目的地址：当目的匹配类型为"主机"、"网段"时才能录入或显示。
			if (MatchTypeEnum.any.toString().equals(desMatchType)) {
				if (!StringUtils.isNullOrEmpty(desAddr) || !StringUtils.isNullOrEmpty(desWildCard)) {
					// 当ip地址匹配类型为"所有主机"时，地址和通配符不可录入。
					return "acl_ace_validate_ip_any";
				}
			} else if (MatchTypeEnum.host.toString().equals(desMatchType)) {
				if (!StringUtils.isNullOrEmpty(desWildCard) || StringUtils.isNullOrEmpty(desAddr)
						|| !AclUtil.wildcardValidator(desAddr)) {
					// 当ip地址匹配类型为"主机"时，必须输入正确的ip地址，通配符不可录入
					return "acl_ace_validate_ip_host";
				}
			} else if (MatchTypeEnum.segment.toString().equals(desMatchType)) {
				if (StringUtils.isNullOrEmpty(desWildCard) || StringUtils.isNullOrEmpty(desAddr)
						|| !AclUtil.wildcardValidator(desAddr) || !AclUtil.wildcardValidator(desWildCard)) {
					// 当ip地址匹配类型为"网段"时，必须输入正确的ip地址和通配符
					return "acl_ace_validate_ip_segment";
				}
			}			
		}
		// [end]
		
		// [start]专家扩展、MAC扩展：MAC地址
		if (AceTypeEnum.MAC.toString().equals(aceType) || AceTypeEnum.EXPERT.toString().equals(aceType)) {

			String sourceMacAddr = ace.getSourceMacAddr();
			String sourceMacMatchType = ace.getSourceMacMatchType();
			if (MacMatchTypeEnum.host.toString().equals(sourceMacMatchType)) {
				// 源MAC地址：当源MAC匹配类型为"主机"时才能录入或显示。
				if (StringUtils.isNullOrEmpty(sourceMacAddr) || !NetUtils.isMACValidate(sourceMacAddr)) {
					// 当mac匹配类型为"主机"时，必须输入正确的mac地址
					return "acl_ace_validate_mac_host";
				}
			} else if (MacMatchTypeEnum.any.toString().equals(sourceMacMatchType)) {
				// 源MAC地址：当源MAC匹配类型为"主机"时才能录入或显示。
				if (!StringUtils.isNullOrEmpty(sourceMacAddr)) {
					// 当mac匹配类型为"所有MAC"时，MAC地址不可录入
					return "acl_ace_validate_mac_mac";
				}
			}

			String desMacAddr = ace.getDesMacAddr();
			String desMacMatchType = ace.getDesMacMatchType();
			if (MacMatchTypeEnum.host.toString().equals(desMacMatchType)) {
				// 目的MAC地址：当目的MAC匹配类型为"主机"时才能录入或显示。
				if (StringUtils.isNullOrEmpty(desMacAddr) || !NetUtils.isMACValidate(desMacAddr)) {
					// 当mac匹配类型为"主机"时，必须输入正确的mac地址
					return "acl_ace_validate_mac_host";
				}
			} else if (MacMatchTypeEnum.any.toString().equals(desMacMatchType)) {
				// 目的MAC地址：当目的MAC匹配类型为"主机"时才能录入或显示。
				if (!StringUtils.isNullOrEmpty(desMacAddr)) {
					// 当mac匹配类型为"所有MAC"时，MAC地址不可录入
					return "acl_ace_validate_mac_mac";
				}
			}
		}
		// [end]
		
		// [start]专家扩展、扩展ACL：源、目的端口

		//[start]扩展、专家扩展：端口。只有tcp和udp才可以显示录入。当tcp时，端口类型为tcp专用端口；当udp时，端口类型为udp专用端口。
		if (AceTypeEnum.EXPERT.toString().equals(aceType) || AceTypeEnum.EXTENDED.toString().equals(aceType)) {
			String protocolType = ace.getProtocolType();
			String sourcePort = ace.getSourcePort();
			String desPort = ace.getDesPort();
			if (ProtocolTypeEnum.tcp.toString().equals(protocolType)
					|| ProtocolTypeEnum.udp.toString().equals(protocolType)) {
				if(!StringUtils.isNullOrEmpty(sourcePort)){
					String sourcePortResult = validatePort(sourcePort,protocolType);
					if (!"".equals(sourcePortResult)) {
						return sourcePortResult;
					}
				}
				if(!StringUtils.isNullOrEmpty(desPort)){
					String desPortResult = validatePort(desPort,protocolType);
					if (!"".equals(desPortResult)) {
						return desPortResult;
					}
				}				
			} else {
				if (!StringUtils.isNullOrEmpty(sourcePort)|| !StringUtils.isNullOrEmpty(desPort)) {
					// 当协议类型不为tcp、udp时，端口不可录入
					return "acl_ace_validate_ip_no_require";
				}
			}
		}
		// [end]
		//[start]描述栏位长度验证
		if(ace.getRemark()!=null&&ace.getRemark().length()>255){
			//acl_ace_validate_remark_maxLength=描述栏位不能超过255个字符！
			return "acl_ace_validate_remark_maxLength";
		}
		//[end]
		return "";//验证成功
	}
	
	/**
	 * 验证组名的合法性


	 * @param text
	 * @param aclType
	 */
	public static String validateGroupName(String text,String aclType){
		Pattern num_pattern = Pattern.compile("[0-9]+");
		//标准IP访问列表的正则表达式
		Pattern std_pattern = Pattern
				.compile("([1-9]|[1-9][0-9])|(1[3-9][0-9]{2,2})");
		//扩展IP访问列表的正则表达式
		Pattern extended_pattern = Pattern
				.compile("(1[0-9]{2,2})|(2[0-6][0-9]{2,2})");
		//MAC扩展访问列表的正则表达式
		Pattern mac_pattern = Pattern.compile("7[0-9]{2,2}");
		//Expert扩展访问列表的正则表达式
		Pattern expert_pattern = Pattern.compile("2[7-8][0-9]{2,2}");
		
		//数字开头，后含非数字正则表达式
		Pattern num_en_pattern=Pattern.compile("\\d.*[^\\d]+.*");
		//以数字开头，却非纯数值


		if(text.length()>99){
			return "acl_group_maxlength";
		}
		if(num_en_pattern.matcher(text).matches()){
			return "acl_validator_group_name__startNum_with_other";
		}
		//[start]数值编号


		if (num_pattern.matcher(text).matches()) {			
			if (aclType == null) {
				return "acl_validator_group_type_reselect";
			}
			if (AceTypeEnum.STANDARD.toString().equals(aclType)) {
				if (!std_pattern.matcher(text).matches()) {
					return "acl_validator_group_name_std";
				}
				
			} else if (AceTypeEnum.EXTENDED.toString().equals(aclType)) {
				if (!extended_pattern.matcher(text).matches()) {
					return "acl_validator_group_name_extended";
				}	
			} else if (AceTypeEnum.MAC.toString().equals(aclType)) {
				if (!mac_pattern.matcher(text).matches()) {
					return "acl_validator_group_name_mac";
				}
			} else if (AceTypeEnum.EXPERT.toString().equals(aclType)) {
				if (!expert_pattern.matcher(text).matches()) {
					return  "acl_validator_group_name_expert";
				}
			} else {
				return "acl_validator_group_type_reselect";
			}
		}//[end]
		return "";
	}

	/**
	 * 验证端口的合法性
	 * 
	 * @param portString
	 * @param type udp或者tcp
	 * @return 合法返回""，不合法返回错误信息
	 */
	public static String validatePort(String portString,String type) {
//		if (StringUtils.isNullOrEmpty(portString)) {
//			return "acl_ace_validate_port_require_4_tcp_udp";
//		}
		if (NUM_PATTERN.matcher(portString).matches()) {
			// 数值
			int port = AclUtil.parseInt(portString);
			if (port < 0 || port > 65535) {
				// 端口值必须在0 ~ 65535之间
				return "acl_ace_validate_port_range_num";
			} else {
				return "";
			}
		} else if (AclUtil.isNotCNAndFullChar(portString)) {
			// 非中文或全角字符
			String portTypeEnum = PortTypeEnum.getEnumValue(portString,type);
			if (portTypeEnum == null) {
				// 端口值必须为某些类型
				return "acl_ace_validate_port_inside_enum";
			} else {
				return "";
			}
		} else {
			return "acl_ace_validate_port_no_cn_full_char";
		}
	}

	/**
	 * 创建UUID
	 * 
	 * @return UUID字符串



	 */
	public static String createUuid() {
		return UUID.randomUUID().toString();
	}

	/**
	 * 转义字符串



	 * 
	 * @param sourceString
	 *            字符串



	 * @return 转义后字符串
	 */
	public static String escapeSpecialString(String sourceString) {
		return escapeSpecialString(sourceString, ESCAPEARRAY);
	}

	/**
	 * 转义字符串



	 * 
	 * @param sourceString
	 *            字符串



	 * @param escapeArray
	 *            转义用数组



	 * @return 转义后字符串
	 */
	public static String escapeSpecialString(String sourceString, String[][] escapeArray) {
		String desString = sourceString;
		for (int i = 0; i < escapeArray.length; i++) {
			desString = desString.replaceAll(escapeArray[i][0], escapeArray[i][1]);
		}
		return desString;
	}

	/**
	 * 反转义字符串
	 * 
	 * @param desString
	 *            字符串



	 * @return 反转义后字符串



	 */
	public static String unescapeSpecialString(String desString) {
		return unescapeSpecialString(desString, ESCAPEARRAY);
	}

	/**
	 * 反转义字符串
	 * 
	 * @param desString
	 *            字符串



	 * @param escapeArray
	 *            反转义用数组
	 * @return 反转义后字符串



	 */
	public static String unescapeSpecialString(String desString, String[][] escapeArray) {
		String sourceString = desString;
		for (int i = 0; i < escapeArray.length; i++) {
			sourceString = sourceString.replaceAll(escapeArray[i][1], escapeArray[i][0]);
		}
		return sourceString;
	}

	/**
	 * 创建唯一编号
	 * 
	 * @return String 唯一编号
	 */
	public static String createUniqueID() {
		String strID;
		if (uniqueID >= 999) {
			uniqueID = 0;
		}
		uniqueID++;
		SimpleDateFormat objFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS", Locale.ENGLISH);
		String dateString = objFormat.format(new Date());
		String uniqueIdStr = "00" + String.valueOf(uniqueID);
		uniqueIdStr = uniqueIdStr.substring(uniqueIdStr.length() - 3);
		strID = dateString + uniqueIdStr;
		return strID;
	}

	public static boolean maskValidator(String mask) {
		String regex = "[0-9]+";
		if (mask == null)
			return false;
		if ("0.0.0.0".equals(mask))
			return true;
		String[] sip = mask.split("\\.");
		for (String str : sip) {
			// 过滤到全角的数字
			if (!str.matches(regex)) {
				return false;
			}
		}
		if (sip.length != 4)
			return false;
		if (mask.lastIndexOf('.') == mask.getBytes().length - 1)
			return false;
		int sip1 = parseInt(sip[0]);
		if (sip1 <= 0 || sip1 > 255)
			return false;
		if (sip1 != 255)
			return false;

		int sip2 = parseInt(sip[1]);
		int sip3 = parseInt(sip[2]);
		if (sip2 < 0 || sip3 < 0 || sip2 > 255 || sip3 > 255)
			return false;

		int sip4 = parseInt(sip[3]);
		if (sip4 < 0 || sip4 > 255)
			return false;

		return true;
	}

	public static boolean ipV4Validator(String ip) {
		return AclUtil.wildcardValidator(ip);
	}

	public static boolean wildcardValidator(String ip) {
		String regex = "[0-9]+";
		if (ip == null)
			return false;
		String[] sip = ip.split("\\.");
		for (String str : sip) {
			// 过滤到全角的数字
			if (!str.matches(regex)) {
				return false;
			}
		}
		if (sip.length != 4)
			return false;
		if (ip.lastIndexOf('.') == ip.getBytes().length - 1)
			return false;

		int sip1 = parseInt(sip[0]);
		int sip2 = parseInt(sip[1]);
		int sip3 = parseInt(sip[2]);
		int sip4 = parseInt(sip[3]);

		if (sip1 < 0 || sip1 > 255)
			return false;
		if (sip2 < 0 || sip3 < 0 || sip2 > 255 || sip3 > 255)
			return false;
		if (sip4 < 0 || sip4 > 255)
			return false;

		return true;
	}

	/**
	 * 测试正则表达式是否正确



	 * 
	 * @param testStr
	 * @param regStr
	 * @return
	 */
	public static boolean testRegex(String testStr, String regStr) {
		RE r = new RE();
		RECompiler compiler = new RECompiler();
		// r.setMatchFlags(RE.MATCH_MULTILINE);
		// r.setProgram((compiler.compile(regStr)));
		// return r.match(testStr);

		r.setMatchFlags(RE.MATCH_SINGLELINE);
		r.setProgram(compiler.compile(new ParserUtil().result(regStr)));
		return (r.match(testStr));
	}

	/**
	 * 检验输入字符串是否不包含中文和全角字符
	 * 
	 * @return 不包含：true;包含:false
	 */
	public static boolean isNotCNAndFullChar(String input) {
		return AclUtil.NOT_CN_FULL_PATTERN.matcher(input).matches();
	}

	/**
	 * 用通配符转换IP
	 * 
	 * @param ip
	 *            IP地址
	 * @param wildcard
	 *            通配符



	 * @return 转换后的IP
	 */
	public static String convertIpWithWildcard(String ip, String wildcard) {
		String resultIp = "";
		int postive = 0xff; // 0000 0000 0000 0000 0000 0000 1111 1111;

		byte[] ipByteArr = NetUtils.ip2bytes(ip);
		byte[] wipByteArr = NetUtils.ip2bytes(wildcard);
		for (int i = 0; i < ipByteArr.length; i++) {
			int value = (byte) ~wipByteArr[i] & ipByteArr[i];
			resultIp += "." + (value & postive); // 取得value的byte型无符号数的值



		}
		return resultIp.substring(1);
		/*
		 * String [] ipArray = ip.split("\\."); String [] wipArray =
		 * wildcard.split("\\."); for (int i = 0; i < ipArray.length; i++){
		 * String convertedIpPart = ""; String ipPart =
		 * Integer.toBinaryString(Integer.parseInt(ipArray[i])); ipPart =
		 * "00000000" + ipPart; ipPart = ipPart.substring(ipPart.length() - 8);
		 * String wipPart =
		 * Integer.toBinaryString(Integer.parseInt(wipArray[i])); wipPart =
		 * "00000000" + wipPart; wipPart = wipPart.substring(wipPart.length() -
		 * 8); for (int j = 0;j < 8; j++){ //为1清0,为0保留 if (wipPart.charAt(j) ==
		 * '1'){ convertedIpPart += "0"; }else{ convertedIpPart +=
		 * ipPart.charAt(j); } } resultIp += "." +
		 * Integer.parseInt(convertedIpPart, 2); } if (resultIp.length() > 0){
		 * resultIp = resultIp.substring(1); } return resultIp;
		 */
	}

	public static String correctMac(String mac){
		if(mac!=null&&NetUtils.isMACValidate(mac)){
			return mac.replaceAll("-", ":").toLowerCase();
		}else{
			return mac;
		}
	}
	
	/**
	 * 判断两个字符串是否相等
	 */
	public static boolean equalString(String s1,String s2){
		return s1==s2||(s1!=null&&s1.equals(s2));
	}
	/**
	 * 比较两个日期时间是否相同，精确到分
	 * @param srcDate 源日期时间
	 * @param desDate 目的日期时间
	 * @return 是否相同
	 */
	public static boolean equals(Date srcDate, Date desDate){
		return equals(srcDate, desDate,"yyyy-MM-dd HH:mm");
	}
	/**
	 * 比较两个日期时间是否相同
	 * @param srcDate 源日期时间
	 * @param desDate 目的日期时间
	 * @param format 格式（通过设置时间格式可以比较不同精度的日期时间）
	 * @return 是否相同
	 */
	public static boolean equals(Date srcDate,Date desDate, String format){
		if(srcDate==desDate){
			return true;
		}else if(srcDate==null&&desDate!=null||desDate==null&&srcDate!=null){
			return false;
		}
		DateFormat df=new SimpleDateFormat(format);
		return df.format(srcDate).equals(df.format(desDate));
	}
	
	/**
	 * 获取一个字符串的hashcode
	 * @param str
	 * @return
	 */
	public static int getStringHashCode(String str){
		if(str!=null){
			return str.hashCode();
		}else{
			return 0;
		}
	}
	
	/**
	 * 过滤并验证accessGroup中的规则
	 * @param accessGroup
	 * @return 返回验证信息，null表示验证成功
	 */
	public static List<String[]> filterAndValidateAccessGroup(AccessGroup accessGroup){
		List<String[]> validaterInfos=new ArrayList<String[]>();
		List<Ace> repeatAces=new ArrayList<Ace>();//用于检验ace的重复性



		List<Ace> aces=accessGroup.getAces();
		int order=1;
		for(int i=0;i<aces.size();order++,i++){
			Ace ace=aces.get(i);
			ace.setOrderNum(order);
			//AclUtil.filterAce(ace, accessGroup.getAclType());
			String validate=AclUtil.validateAce(ace, accessGroup.getAclType());
			if(!"".equals(validate)){
				//ACE规则验证失败
				aces.remove(i);
				i--;
				//警告：{0}号规则导入失败！失败原因：{1}
				validaterInfos.add(new String[]{"acl_group_ace_import_failed_filter",new Integer(order).toString(),validate});
			}else{
				int index=repeatAces.indexOf(ace);
				if(index>=0){
					//出现重复
					Ace repeatAce=aces.get(index);
					aces.remove(i);
					i--;
					//警告：{0}号规则导入失败！失败原因：与{1}号规则重复！
					validaterInfos.add(new String[]{
							"acl_group_ace_import_failed_repeat",
							new Integer(order).toString(),
							new Integer(repeatAce.getOrderNum()).toString()
							});
				}else{
					repeatAces.add(ace);
				}
			}
			
		}
		return validaterInfos.size()==0?null:validaterInfos;
	}
	
	/**
	 * 解析字符串，将code中的{数值}用params中的参数进行代替
	 * 没有找到相应的参数时，{数值}被忽略
	 * @param code
	 * @return
	 */
	public static String replateWithParam(String code,String... params){
		if(params==null||params.length==0){
			return code;
		}
		Pattern paramPattern=Pattern.compile("\\{\\d+\\}");
		Matcher matcher=paramPattern.matcher(code);
		StringBuffer output=new StringBuffer();
		int preStart = -1;
		int preEnd = 0;
		while(matcher.find()){
			int start=matcher.start();
			int end=matcher.end();
			if (preStart < 0) {
				output.append(code.substring(0, start));
			} else {
				output.append(code.substring(preEnd, start));
			}
			String indexStr=code.substring(start+1,end-1);
			int index=Integer.parseInt(indexStr);
			if(index>=0&&index<params.length){
				output.append(params[index]);
			}
			preStart=start;
			preEnd=end;
		}
		output.append(code.substring(preEnd));
		return output.length()==0?code:output.toString();
	}
	
	/**
	 * 比较以太网类型是否一致，比较规则为:null=""="etype-any"
	 * @param ethernetType
	 * @param other
	 * @return
	 */
	public static boolean compareEthernetType(String ethernetType,String other){
		String temp1=ethernetType,temp2=other;
		if(ethernetType==null||ethernetType.trim().length()==0||
				EthernetTypeEnum.etype_any.toString().equals(ethernetType)){
			temp1=null;
		}
		if(other==null||other.trim().length()==0||
				EthernetTypeEnum.etype_any.toString().equals(other)){
			temp2=null;
		}
		return AclUtil.equalString(temp1, temp2);
	}
	
	/*
	 * 过滤数值前面零
	 */
	public static String trimZero(String num){
		int value;
		try{
			value=Integer.parseInt(num);
		}catch(Exception e){
			return num;
		}
		return String.valueOf(value);
	}
	
}
